package com.baosight.risk.service.fltd.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baosight.risk.api.fltd.AuthoTypeService;
import com.baosight.risk.api.fltd.FlaaFlowCheckService;
import com.baosight.risk.api.fltd.FlaaNodeAuthoService;
import com.baosight.risk.api.fltd.FlaaNodeService;
import com.baosight.risk.api.fltd.FltdPressService;
import com.baosight.risk.api.fltd.FltdProcessService;
import com.baosight.risk.api.fltd.FltdTaskService;
import com.baosight.risk.api.xtaa.code.IXtaaCodeService;
import com.baosight.risk.api.xtzy.IXtzyCompanyService;
import com.baosight.risk.common.bean.BeanUtils;
import com.baosight.risk.common.constant.WorkflowConstant;
import com.baosight.risk.common.utils.StringUtils;
import com.baosight.risk.mapper.fltd.FlaaNodeAuthoMapper;
import com.baosight.risk.service.fltd.entity.FlaaFlowCheck;
import com.baosight.risk.service.fltd.entity.FlaaNode;
import com.baosight.risk.service.fltd.entity.FlaaNodeAutho;
import com.baosight.risk.service.fltd.entity.FltdTask;
import com.baosight.risk.service.fltd.vo.FlaaFlowCheckVO;
import com.baosight.risk.service.fltd.vo.FlaaNodeAuthoTypeVO;
import com.baosight.risk.service.fltd.vo.FlaaNodeAuthoVO;
import com.baosight.risk.service.fltd.vo.FlaaNodeVO;
import com.baosight.risk.service.fltd.vo.FltdTaskVO;
import com.baosight.risk.service.fltd.vo.NodeTransitionVO;
import com.baosight.risk.service.xtaa.code.entity.XtaaCode;
import com.baosight.risk.service.xtzy.entity.XtzyUser;

import lombok.extern.slf4j.Slf4j;

/**
 * 作者： lishaoqing
 * 时间： 2019年07月17日
 * 描述： FlaaNodeAuthoServiceImpl
 * 版本: v1.0
 */
@Service
@Slf4j
public class FlaaNodeAuthoServiceImpl implements FlaaNodeAuthoService {

    @Autowired
    private FlaaNodeAuthoMapper flaaNodeAuthoMapper;

    @Autowired
    private IXtzyCompanyService companyService;

    @Autowired
    private FltdProcessService fltdProcessService;

    @Autowired
    private FltdTaskService fltdTaskService;

    @Autowired
    private FlaaFlowCheckService flaaFlowCheckService;

    @Autowired
    private FlaaNodeService flaaNodeService;

    @Autowired
    private FltdPressService fltdPressService;

    @Autowired
    private AuthoTypeService authoTypeService;

    @Autowired
    private IXtaaCodeService xtaaCodeService;

    @Override
    public void save(List<FlaaNodeAuthoVO> nodes, String userCode) throws Exception {
        try {
            Date now = new Date();
            if (CollectionUtils.isNotEmpty(nodes)) {
                for (FlaaNodeAuthoVO auth : nodes) {
                    //添加参与者授权配置
                    if (CollectionUtils.isNotEmpty(auth.getAuthoList())) {
                        for (FlaaNodeAuthoTypeVO authoTypeVO : auth.getAuthoList()) {
                            FlaaNodeAutho flaaNodeAutho = new FlaaNodeAutho();
                            //复制节点参数
                            BeanUtils.copyBeanProp(flaaNodeAutho, auth);
                            //复制参与者授权参数
                            BeanUtils.copyBeanProp(flaaNodeAutho, authoTypeVO);
                            flaaNodeAutho.setNotAuthoGuid(UUID.randomUUID().toString());
                            flaaNodeAutho.setCreateBy(userCode);
                            flaaNodeAutho.setCreateTime(now);
                            //添加流程授权规则
                            if (flaaNodeAuthoMapper.insert(flaaNodeAutho) == 0) {
                                throw new Exception("新增流程授权规则失败");
                            }
                        }
                    }

                    //添加节点扩展属性配置
                    List<FlaaNodeVO> extList = auth.getExtList();
                    if (CollectionUtils.isNotEmpty(extList)) {
                        for (FlaaNodeVO flaaNodeVO : extList) {
                            FlaaNode ext = new FlaaNode();
                            BeanUtils.copyBeanProp(ext, flaaNodeVO);
                            BeanUtils.initBean(ext);
                            if (flaaNodeService.insert(ext) == 0) {
                                throw new Exception("新增节点扩展属性配置失败");
                            }
                        }
                    }

                    //添加节点事件配置
                    List<FlaaFlowCheckVO> nodeHandler = auth.getNodeHandler();
                    if (CollectionUtils.isNotEmpty(nodeHandler)) {
                        for (FlaaFlowCheckVO checkVO : nodeHandler) {
                            FlaaFlowCheck check = new FlaaFlowCheck();
                            BeanUtils.copyBeanProp(check, checkVO);
                            BeanUtils.initBean(check);
                            if (flaaFlowCheckService.insert(check) == 0) {
                                throw new Exception("新增节点事件配置失败");
                            }
                        }
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        }
    }

    @Override
    public void cleanNodes(List<FlaaNodeAuthoVO> nodes) throws Exception {
        try {
            for (FlaaNodeAuthoVO node : nodes) {
                if ("Y".equals(node.getAuthStatus())) {
                    //先删除之前的节点授权配置
                    flaaNodeAuthoMapper.deleteFlowAutho(node.getFlowNo(), node.getNodeCode());
                }

                if (CollectionUtils.isNotEmpty(node.getExtList())) {
                    //先删除之前的扩展属性配置
                    flaaNodeService.deleteFlowNode(node.getFlowNo(), node.getNodeCode());
                }

                if (CollectionUtils.isNotEmpty(node.getNodeHandler())) {
                    //先删除之前的事件配置
                    flaaFlowCheckService.deleteFlowCheck(node.getFlowNo(), node.getNodeCode());
                }
            }
        } catch (Exception e) {
            log.error("操作失败！"+e.getMessage());
            throw new Exception("操作失败！"+e.getMessage());
        }

    }

    @Override
    public void update(List<FlaaNodeAuthoVO> nodes, String userCode) throws Exception {
        try {
            Date now = new Date();
            for (FlaaNodeAuthoVO node : nodes) {
                //更新节点授权配置
                for (FlaaNodeAuthoTypeVO authoTypeVO : node.getAuthoList()) {
                    FlaaNodeAutho nodeAutho = new FlaaNodeAutho();
                    BeanUtils.copyBeanProp(nodeAutho, node);
                    BeanUtils.copyBeanProp(nodeAutho, authoTypeVO);
                    nodeAutho.setNotAuthoGuid(UUID.randomUUID().toString());
                    nodeAutho.setUpdateBy(userCode);
                    nodeAutho.setUpdateTime(now);
                    if (flaaNodeAuthoMapper.insert(nodeAutho) == 0) {
                        throw new Exception("更新节点授权配置失败");
                    }
                }

                //更新节点扩展属性配置
                List<FlaaNodeVO> extList = node.getExtList();
                if (CollectionUtils.isNotEmpty(extList)) {
                    for (FlaaNodeVO flaaNodeVO : extList) {
                        FlaaNode ext = new FlaaNode();
                        BeanUtils.copyBeanProp(ext, flaaNodeVO);
                        BeanUtils.initBean(ext);
                        ext.setUpdateBy(userCode);
                        ext.setUpdateTime(now);
                        if (flaaNodeService.insert(ext) == 0) {
                            throw new Exception("更新节点扩展属性配置失败");
                        }
                    }
                }

                //更新节点事件处理
                List<FlaaFlowCheckVO> nodeHandler = node.getNodeHandler();
                if (CollectionUtils.isNotEmpty(nodeHandler)) {
                    for (FlaaFlowCheckVO checkVO : nodeHandler) {
                        FlaaFlowCheck check = new FlaaFlowCheck();
                        BeanUtils.copyBeanProp(check, checkVO);
                        BeanUtils.initBean(check);
                        check.setUpdateBy(userCode);
                        check.setUpdateTime(now);
                        if (flaaFlowCheckService.insert(check) == 0) {
                            throw new Exception("更新节点事件配置失败");
                        }
                    }
                }

            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }

    @Override
    public List<FlaaNodeAuthoVO> selectNodesByFlowNo(String flowNo) {
        List<FlaaNodeAutho> nodeAuthos = flaaNodeAuthoMapper.selectNodesByFlowNo(flowNo);
        List<FlaaNodeAuthoVO> nodes = parseNodeAuthoVO(nodeAuthos);

        List<String> list = new ArrayList<>();
        for (FlaaNodeAuthoVO node : nodes) {
            node.setAuthStatus("Y");
            list.add(node.getNodeCode());
        }
        List<FlaaNodeAutho> notAuthNodes = flaaNodeAuthoMapper.selectNotAuthNodes(flowNo, list);
        for (FlaaNodeAutho notAuthNode : notAuthNodes) {
            FlaaNodeAuthoVO node = new FlaaNodeAuthoVO();
            BeanUtils.copyBeanProp(node, notAuthNode);
            node.setAuthoList(new ArrayList<>());
            node.setAuthStatus("N");
            nodes.add(node);
        }

        //自定义排序
        sortNodes(flowNo, nodes);

        for (FlaaNodeAuthoVO nodeAutho : nodes) {
            //查询节点的扩展属性配置
            List<FlaaNodeVO> extList = new ArrayList<>();
            FlaaNodeVO urgent = flaaNodeService.selectUrgent(nodeAutho.getFlowNo(), nodeAutho.getNodeCode());
            if (urgent != null) {
                extList.add(urgent);
            }
            List<FlaaNodeVO> nodeList = flaaNodeService.selectFlowNode(nodeAutho.getFlowNo(), nodeAutho.getNodeCode());
            if (CollectionUtils.isNotEmpty(nodeList)) {
                extList.addAll(nodeList);
            }
            nodeAutho.setExtList(extList);
            //查询节点的事件配置
            nodeAutho.setNodeHandler(flaaFlowCheckService.selectFlowCheck(nodeAutho.getFlowNo(), nodeAutho.getNodeCode()));
        }
        return nodes;
    }

    @Override
    public FlaaNodeAuthoVO selectNodeInfo(String flowNo, String nodeCode) {
        List<FlaaNodeAutho> list = flaaNodeAuthoMapper.selectNodeInfo(flowNo, nodeCode);
        if (CollectionUtils.isNotEmpty(list)) {
            return parseNodeAuthoVO(list).get(0);
        }
        return null;
    }

    @Override
    public FlaaNodeAuthoVO selectFirstNode(String flowNo, String nodeType) {
        List<FlaaNodeAutho> list = flaaNodeAuthoMapper.selectNextNodesByNodeType(flowNo, nodeType);
        if (CollectionUtils.isNotEmpty(list)) {
            return parseNodeAuthoVO(list).get(0);
        }
        return null;
    }

    @Override
    public FlaaNodeAuthoVO selectNextNode(String processDefId, String flowNo, String nodeCode) {
        List<FlaaNodeAutho> list = flaaNodeAuthoMapper.selectNextNode(processDefId, flowNo, nodeCode);
        if (CollectionUtils.isNotEmpty(list)) {
            return parseNodeAuthoVO(list).get(0);
        }
        return null;
    }

    @Override
    public List<NodeTransitionVO> selectNextNodeTransition(String processDefId, String nodeCode) {
        return flaaNodeAuthoMapper.selectNextNodeTransition(processDefId, nodeCode);
    }

    @Override
    public List<NodeTransitionVO> selectTransition(String processDefId, String nodeCode) {
        return flaaNodeAuthoMapper.selectTransition(processDefId, nodeCode);
    }

    @Override
    public NodeTransitionVO selectTransitionById(String transitionDefId,String processDefId) {
        return flaaNodeAuthoMapper.selectTransitionById(transitionDefId,processDefId);
    }

    @Override
    public NodeTransitionVO selectNodeByType(String processDefId, String nodeType) {
        return flaaNodeAuthoMapper.selectNodeByType(processDefId, nodeType);
    }

    /**
     * 查询给定节点的组织、用户列表
     *
     * @param nodeInfo    节点vo
     * @param currentUser 当前用户
     * @param currentTask 待办任务vo
     */
    @Override
    public Map<String, Object> getUsersByNodeInfo(FlaaNodeAuthoVO nodeInfo, XtzyUser currentUser, FltdTaskVO currentTask) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if(nodeInfo == null){
                return resultMap;
            }
            if (CollectionUtils.isNotEmpty(currentTask.getCustomUsers())) {
                resultMap.put("userList", currentTask.getCustomUsers());
            } else {
                //所有参与者
                List<XtzyUser> allUsers = new ArrayList<>();
                //流程审批参与者
                List<XtzyUser> authUsers = new ArrayList<>();
                //通知提醒参与者
                List<XtzyUser> remindUsers = new ArrayList<>();
                //其他类型参与者
                List<XtzyUser> otherUsers = new ArrayList<>();
                List<FlaaNodeAuthoTypeVO> authoList = nodeInfo.getAuthoList();
                for (FlaaNodeAuthoTypeVO authoTypeVO : authoList) {
                    //流程参与者
                    List<XtzyUser> userList = new ArrayList<>();
                    Map<String, Object> param = new HashMap<>();
                    param.put("authInfo", authoTypeVO);
                    param.put("currentUser", currentUser);
                    param.put("currentTask", currentTask);
                    param.put("userList", userList);
                    authoTypeService.parse(authoTypeVO.getAuthoRange(), param);
                    allUsers.addAll(userList);
                    if ("1".equals(authoTypeVO.getTodoType())) {
                        authUsers.addAll(userList);
                    } else if ("2".equals(authoTypeVO.getTodoType())) {
                        for (XtzyUser remindUser : userList) {
                            remindUser.setRemark(authoTypeVO.getRemind());
                        }
                        remindUsers.addAll(userList);
                    } else if ("9".equals(authoTypeVO.getTodoType())) {
                        otherUsers.addAll(userList);
                    }
                }
                resultMap.put("allUsers", allUsers);
                resultMap.put("authUsers", authUsers);
                resultMap.put("remindUsers", remindUsers);
                resultMap.put("otherUsers", otherUsers);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }
        return resultMap;
    }

    /**
     * 校验开始节点权限
     *
     * @param taskVO      流程任务vo
     * @param currentUser 当前用户
     * @return 校验结果
     */
    @Override
    public Map<String, Object> validStart(FltdTaskVO taskVO, XtzyUser currentUser) {
        Map<String, Object> map = new HashMap<>();
        //查询第一个人工节点的授权信息
        FlaaNodeAuthoVO firstNode = selectFirstNode(taskVO.getFlowNo(), WorkflowConstant.PROCESS_START);
        if (firstNode == null) {
            //流程未授权或者入参错误
            map.put("code", "1");
            return map;
        }

        //校验当前登录人是否有流程启动权限
        boolean check = false;
        //所有参与者
        List<XtzyUser> allUsers = new ArrayList<>();
        try {
            List<FlaaNodeAuthoTypeVO> authoList = firstNode.getAuthoList();
            for (FlaaNodeAuthoTypeVO authoTypeVO : authoList) {
                Map<String, Object> param = new HashMap<>();
                param.put("currentTask", taskVO);
                param.put("authInfo", authoTypeVO);
                param.put("currentUser", currentUser);
                param.put("userList", allUsers);
                authoTypeService.parse(authoTypeVO.getAuthoRange(), param);
            }
            for (XtzyUser user : allUsers) {
                if (currentUser.getUserCode().equals(user.getUserCode())) {
                    check = true;
                    break;
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        if (!check) {
            //当前用户无权启动此流程
            map.put("code", "2");
        } else {
            map.put("firstNode", firstNode);
            map.put("nextNode", selectNextNode(null, taskVO.getFlowNo(), firstNode.getNodeCode()));
            map.put("code", "0");
        }
        return map;
    }

    /**
     * 获取流程转移路径
     *
     * @param taskVO 流程任务vo
     * @return 流程转移路径
     */
    @Override
    public Map<String, Object> getTransitionButton(FltdTaskVO taskVO) {
        Map<String, Object> resultMap = new HashMap<>();
        List<NodeTransitionVO> transitions = new ArrayList<>();
        Map<String, Object> variables = new HashMap<>();
        String code = "0";
        String msg = "";

        //查询当前待办信息
        FltdTask currentTask = fltdTaskService.selectTaskByTodoGuid(taskVO.getTodoGuid());
        if (currentTask == null) {
            code = "1";
            msg = "没有未处理的待办";
        } else {
            //当前流程的流程定义id
            String processDefId = fltdProcessService.getProcessDefId(currentTask.getProcGuid());
            if (StringUtils.isEmpty(processDefId)) {
                code = "2";
                msg = "流程定义错误";
            }

            //当前节点的授权信息
            FlaaNodeAuthoVO currentNodeInfo = selectNodeInfo(currentTask.getFlowNo(), currentTask.getNodeCode());

            //当前节点的转移路径
            transitions = flaaNodeAuthoMapper.selectTransition(processDefId, currentTask.getNodeCode());
            String nodeType = transitions.get(0).getNodeType();
            String nodeKey = transitions.get(0).getNodeKey();
            //下一个节点是条件分支
            if (WorkflowConstant.PROCESS_INCLUSIVEGATEWAY.equals(nodeType)) {
                transitions = flaaNodeAuthoMapper.selectNextNodeTransition(processDefId, currentTask.getNodeCode());
                //绿色通道的条件分支
                if (nodeKey.contains(WorkflowConstant.PROCESS_SUBMITPATH)) {
                    //判断当前节点是否带有绿色通道标识
                    boolean check = true;
                    if (fltdProcessService.convertExt(currentNodeInfo.getFlowNo(), currentNodeInfo.getNodeCode(), variables)) {
                        String greeFlag = (String) variables.get("greeFlag");
                        if (StringUtils.isNotEmpty(greeFlag) && "G".equals(greeFlag)) {
                            check = false;
                        }
                    }

                    //判断当前待办是否有绿色通道标识
                    if (check) {
                        if ("G".equals(currentTask.getGreenFlag())) {
                            //绿色通道提交
                            List<NodeTransitionVO> list = new ArrayList<>();
                            for (NodeTransitionVO transition : transitions) {
                                if (transition.getTransitionKey().contains("submit-G")) {
                                    list.add(transition);
                                }
                            }
                            transitions = list;
                        } else {
                            List<NodeTransitionVO> list = new ArrayList<>();
                            for (NodeTransitionVO transition : transitions) {
                                if (transition.getTransitionKey().contains("submit-N")) {
                                    list.add(transition);
                                }
                            }
                            transitions = list;
                        }
                    }
                }
            }
        }

        resultMap.put("code", code);
        resultMap.put("msg", msg);
        resultMap.put("transitions", transitions);
        return resultMap;
    }

    /**
     * 获取下一节点审批人
     *
     * @param taskVO      流程任务vo
     * @param currentUser 当前用户
     */
    @Override
    public Map<String, Object> getNextUser(FltdTaskVO taskVO, XtzyUser currentUser) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        List<NodeTransitionVO> transitions = new ArrayList<>();

        //所有参与者
        List<XtzyUser> allUsers = new ArrayList<>();
        //流程审批参与者
        List<XtzyUser> authUsers = new ArrayList<>();
        //通知提醒参与者
        List<XtzyUser> remindUsers = new ArrayList<>();
        //其他类型参与者
        List<XtzyUser> otherUsers = new ArrayList<>();

        NodeTransitionVO submitTransition = null;
        String code = "0";
        String msg = "";

        //查询当前待办信息
        FltdTask currentTask = fltdTaskService.selectTaskByTodoGuid(taskVO.getTodoGuid());
        currentTask.setExt5(taskVO.getExt5());
        BeanUtils.copyBeanProp(taskVO, currentTask);
        if (currentTask == null) {
            code = "1";
            msg = "没有未处理的待办";
        } else {

            //当前流程的流程定义id
            String processDefId = fltdProcessService.getProcessDefId(currentTask.getProcGuid());
            if (StringUtils.isEmpty(processDefId)) {
                code = "2";
                msg = "流程定义错误";
            }

            //当前节点的转移路径
            transitions = flaaNodeAuthoMapper.selectTransition(processDefId, currentTask.getNodeCode());
            String nodeType = transitions.get(0).getNodeType();

            //下一个节点是条件分支
            if (WorkflowConstant.PROCESS_INCLUSIVEGATEWAY.equals(nodeType)) {
                transitions = flaaNodeAuthoMapper.selectNextNodeTransition(processDefId, currentTask.getNodeCode());
                String findName = "submit-" + currentTask.getGreenFlag();
                for (NodeTransitionVO transition : transitions) {
                    //刷新转移线
                    NodeTransitionVO branch = selectTransitionById(transition.getTransitionDefId(),transition.getProcessDefId());
                    if (WorkflowConstant.PROCESS_END.equals(branch.getNodeType())) {
                        //其中一条分支是结束节点
                        resultMap.put("isEnd", "1");
                    } else if (branch.getTransitionKey().contains(findName)) {
                        //提交的分支
                        submitTransition = branch;
                        break;
                    }
                }
            } else {
                submitTransition = selectTransitionById(transitions.get(0).getTransitionDefId(),transitions.get(0).getProcessDefId());
                if (WorkflowConstant.PROCESS_END.equals(submitTransition.getNodeType())) {
                    //下一个节点是结束节点
                    resultMap.put("code", "0");
                    resultMap.put("isEnd", "1");
                    return resultMap;
                }
            }

            if (submitTransition != null) {
                if (!"Y".equals(taskVO.getExt5())) {
                    FlaaNodeAuthoVO nodeInfo = selectNodeInfo(currentTask.getFlowNo(), submitTransition.getNodeKey());
                    if (nodeInfo == null) {
                        code = "3";
                        msg = "节点[ "+submitTransition.getNodeName()+" ]未授权！当前部门：" + currentTask.getDeptName();
                    } else {
                        try {
                            Map<String, Object> queryMap = getUsersByNodeInfo(nodeInfo, currentUser, taskVO);
                            allUsers = (List<XtzyUser>) queryMap.get("allUsers");
                            authUsers = (List<XtzyUser>) queryMap.get("authUsers");
                            remindUsers = (List<XtzyUser>) queryMap.get("remindUsers");
                            otherUsers = (List<XtzyUser>) queryMap.get("otherUsers");
                            if (authUsers == null || authUsers.size() == 0) {
                                code = "4";
                                msg = "节点[ "+nodeInfo.getNodeName()+" ]未配置待办审批人！当前部门：" + currentTask.getDeptName();
                            }
                        }catch (Exception e){
                            log.error(e.getMessage());
                            throw e;
                        }
                    }
                }
            }
        }

        resultMap.put("code", code);
        resultMap.put("msg", msg);
        resultMap.put("allUsers", allUsers);
        resultMap.put("authUsers", authUsers);
        resultMap.put("remindUsers", remindUsers);
        resultMap.put("otherUsers", otherUsers);
        resultMap.put("submitTransition", submitTransition);
        return resultMap;
    }

    /**
     * 获取下一节点审批人，包含多个分支的人员
     *
     * @param taskVO      流程任务vo
     * @param currentUser 当前用户
     */
    @Override
    public Map<String, Object> getNextUserBranch(FltdTaskVO taskVO, XtzyUser currentUser) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        List<NodeTransitionVO> transitions = new ArrayList<>();
        NodeTransitionVO submitTransition = null;
        String code = "0";
        String msg = "";

        List<Map<String, Object>> branchs = new ArrayList<>();

        //查询当前待办信息
        FltdTask currentTask = fltdTaskService.selectTaskByTodoGuid(taskVO.getTodoGuid());
        currentTask.setExt1(taskVO.getExt1());
        BeanUtils.copyBeanProp(taskVO, currentTask);
        if (currentTask == null) {
            code = "1";
            msg = "没有未处理的待办";
        } else {

            //当前流程的流程定义id
            String processDefId = fltdProcessService.getProcessDefId(currentTask.getProcGuid());
            if (StringUtils.isEmpty(processDefId)) {
                code = "2";
                msg = "流程定义错误";
            }

            //当前节点的转移路径
            transitions = flaaNodeAuthoMapper.selectTransition(processDefId, currentTask.getNodeCode());
            String nodeType = transitions.get(0).getNodeType();

            //下一个节点是条件分支
            if (WorkflowConstant.PROCESS_INCLUSIVEGATEWAY.equals(nodeType)) {
                transitions = flaaNodeAuthoMapper.selectNextNodeTransition(processDefId, currentTask.getNodeCode());
                String findName = "submit-" + currentTask.getGreenFlag();
                for (NodeTransitionVO transition : transitions) {
                    Map<String, Object> map = new HashMap<>();
                    //刷新转移线
                    NodeTransitionVO branch = selectTransitionById(transition.getTransitionDefId(),transition.getProcessDefId());

                    if (WorkflowConstant.PROCESS_END.equals(branch.getNodeType())) {
                        //其中一条分支是结束节点
                        map.put("isEnd", "1");
                        map.put("submitTransition", branch);
                    } else if (branch.getTransitionKey().contains(findName)) {
                        //提交的分支
                        map.put("submitTransition", branch);
                    }
                    if (map.size() > 0 ){
                        branchs.add(map);
                    }
                }
            } else {
                Map<String, Object> map = new HashMap<>();
                submitTransition = selectTransitionById(transitions.get(0).getTransitionDefId(),transitions.get(0).getProcessDefId());
                map.put("submitTransition", submitTransition);
                branchs.add(map);
                if (WorkflowConstant.PROCESS_END.equals(submitTransition.getNodeType())) {
                    //下一个节点是结束节点
                    map.put("isEnd", "1");
                    resultMap.put("code", "0");
                    resultMap.put("users", branchs);
                    return resultMap;
                }
            }

            if (CollectionUtils.isNotEmpty(branchs)) {
                if (!"Y".equals(taskVO.getExt1())) {
                    for (Map<String, Object> map : branchs) {
                        NodeTransitionVO transition = (NodeTransitionVO) map.get("submitTransition");
                        if (transition == null || "1".equals(map.get("isEnd"))) continue;
                        FlaaNodeAuthoVO nodeInfo = selectNodeInfo(currentTask.getFlowNo(), transition.getNodeKey());
                        if (nodeInfo == null) {
                            code = "3";
                            msg = "节点[ "+transition.getNodeName()+" ]未授权！当前部门：" + currentTask.getDeptName();
                            break;
                        } else {
                            try {
                                Map<String, Object> queryMap = getUsersByNodeInfo(nodeInfo, currentUser, taskVO);
                                List<XtzyUser> authUsers = (List<XtzyUser>) queryMap.get("authUsers");
                                if (CollectionUtils.isEmpty(authUsers)) {
                                    code = "4";
                                    msg = "节点[ "+nodeInfo.getNodeName()+" ]未配置待办审批人！当前部门：" + currentTask.getDeptName();
                                } else {
                                    map.put("userList", authUsers);
                                }
                            }catch (Exception e){
                                log.error(e.getMessage());
                                throw new Exception("操作异常："+e.getMessage());
                            }
                        }
                    }

                }
            }
        }

        resultMap.put("code", code);
        resultMap.put("msg", msg);
        resultMap.put("branchs", branchs);
        return resultMap;
    }

    /**
     * 转换数据库查询的节点授权列表
     *
     * @return 转换结果
     */
    private List<FlaaNodeAuthoVO> parseNodeAuthoVO(List<FlaaNodeAutho> nodeAuthos) {
        //根据节点去重
        List<FlaaNodeAuthoVO> nodes = new ArrayList<>();
        Map<String, FlaaNodeAuthoVO> map = new HashMap<>();
        for (FlaaNodeAutho nodeAutho : nodeAuthos) {
            String key = nodeAutho.getFlowNo() + nodeAutho.getNodeCode();
            if (map.containsKey(key)) {
                FlaaNodeAuthoVO authoVO = map.get(key);
                List<FlaaNodeAuthoTypeVO> authoList = authoVO.getAuthoList();
                FlaaNodeAuthoTypeVO typeVO = new FlaaNodeAuthoTypeVO();
                BeanUtils.copyBeanProp(typeVO, nodeAutho);
                authoList.add(typeVO);
            } else {
                FlaaNodeAuthoVO authoVO = new FlaaNodeAuthoVO();
                BeanUtils.copyBeanProp(authoVO, nodeAutho);

                List<FlaaNodeAuthoTypeVO> authoList = new ArrayList<>();
                FlaaNodeAuthoTypeVO typeVO = new FlaaNodeAuthoTypeVO();
                BeanUtils.copyBeanProp(typeVO, nodeAutho);
                authoList.add(typeVO);
                authoVO.setAuthoList(authoList);
                map.put(key, authoVO);
                nodes.add(authoVO);
            }
        }
        return nodes;
    }

    private void sortNodes(String flowNo, List<FlaaNodeAuthoVO> nodes){
        boolean sortByCode = false;
        String ddTypeCode = getDDTypeCode(flowNo);
        if(StringUtils.isNotEmpty(ddTypeCode)){
            try {
                Map<String, String> codeMap = new HashMap<>();
                List<XtaaCode> xtaaCodes = xtaaCodeService.selectDataByDDTypeCode(ddTypeCode);
                for (XtaaCode xtaaCode : xtaaCodes) {
                    codeMap.put(xtaaCode.getDdCode(), xtaaCode.getRowOrder());
                }
                for (FlaaNodeAuthoVO node : nodes) {
                    if (codeMap.containsKey(node.getNodeCode())) {
                        node.setCustRowOrder(codeMap.get(node.getNodeCode()));
                    } else {
                        node.setCustRowOrder(node.getNodeCode());
                    }
                }
                //根据字典排序
                Collections.sort(nodes, Comparator.comparing(FlaaNodeAuthoVO::getCustRowOrder));
            }catch (Exception e){
                e.printStackTrace();
                sortByCode = true;
            }
        }else{
            sortByCode = true;
        }

        if (sortByCode) {
            //根据编码排序
            Collections.sort(nodes, Comparator.comparing(FlaaNodeAuthoVO::getNodeCode));
        }
    }

    private String getDDTypeCode(String flowNo){
        String DDTypeCode = "";
        switch(flowNo){
            case "fengxianjieti":
            case "fengxianjieticeping":
                DDTypeCode = "RIIM_CLOSE_STATUS";
                break;
            case "fengxianziping":
                DDTypeCode = "RIRI_RISK_STATUS";
                break;
            case "fengxiandangan":
                DDTypeCode = "RIDC_STATUS";
                break;
            case "wenjuantianbao":
                DDTypeCode = "RIQU_REBACK_STATUS";
                break;
            case "fengxianshishifangan":
                DDTypeCode = "RIIM_PLAN_STATUS";
                break;
            case "fengxianpilubaogao":
                DDTypeCode = "RIIM_REPORT_STATUS";
                break;
            case "jidifengxianpilubaogao":
                DDTypeCode = "RIIM_REPORT_STATUS";
                break;
            case "jidiziping":
                DDTypeCode = "RIRI_RISK_STATUS";
                break;
            case "jidishishifangan":
                DDTypeCode = "RIIM_PLAN_STATUS";
                break;
            case "jididangan":
                DDTypeCode = "RIDC_STATUS";
                break;

            default:
                break;
        }
        return DDTypeCode;
    }

}
